home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / os2 / eaclib.zip / EALIST.CPP < prev    next >
C/C++ Source or Header  |  1996-05-22  |  21KB  |  637 lines

  1. /* --------------------------------------------------------------------------
  2.  * $RCSfile: EAList.cpp,v $
  3.  * $Revision: 1.1 $
  4.  * $Date: 1996/05/22 20:59:55 $
  5.  * $Author: Bablok $
  6.  * --------------------------------------------------------------------------
  7.  * Synopsis:
  8.  *
  9.  * Implementation of class EAList. This class wraps the extended attributes API
  10.  * of OS/2 and handles complete sets of file-EAs.
  11.  *
  12.  * An EAList is implemented as a key sorted set. This allows the conversion
  13.  * of an EAList to a multivalued EA and back again.
  14.  *
  15.  * This file is part of the EA classlib package.
  16.  * Copyright Bernhard Bablok, 1996
  17.  *
  18.  * The EA classlib package is distributed in the hope that it will be
  19.  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  20.  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  21.  *
  22.  * You may use the classes in the package to any extend you wish. You are
  23.  * allowed to change and copy the source of the classes, as long as you keep
  24.  * the copyright notice intact and as long as you document the changes you made.
  25.  *
  26.  * You are not allowed to sell the EA classlib package or a modified version
  27.  * thereof, but you may charge for costs of distribution media.
  28.  *
  29.  * --------------------------------------------------------------------------
  30.  * Change-Log:
  31.  *
  32.  * $Log: EAList.cpp,v $
  33.  * Revision 1.1  1996/05/22 20:59:55  Bablok
  34.  * Initial revision
  35.  *
  36.  * -------------------------------------------------------------------------- */
  37.  
  38. #ifndef _IEXCEPT_
  39.    #include <iexcept.hpp>
  40. #endif
  41. #ifndef _IMSGTEXT_
  42.    #include <imsgtext.hpp>
  43. #endif
  44. #ifndef __iostream_h
  45.    #include <iostream.h>
  46. #endif
  47. #ifndef __math_h
  48.    #include <math.h>
  49. #endif
  50.  
  51. #ifndef EA_H
  52.    #include "EA.hpp"
  53. #endif
  54. #ifndef EALIST_H
  55.    #include "EAList.hpp"
  56. #endif
  57.  
  58. ///////////////////////////////////////////////////////////////////////////////
  59. // Copy constructor
  60. //
  61. EAList::EAList(const EAList& eaList) : EASet(EALIST_DEFAULT_SIZE),
  62.                                                                mFEA2List(NULL) {
  63.    if (eaList.mFEA2List) {
  64.       ULONG length = *(ULONG*) eaList.mFEA2List;
  65.       char *buffer = new char[length];
  66.       if (!buffer) {
  67.          IOutOfMemory exc(IMessageText(ERR_MEM_ALLOC_FAILED,MSG_FILE),0);
  68.          ITHROW(exc);
  69.       }
  70.       memcpy(buffer,(char*) eaList.mFEA2List,length);
  71.       mFEA2List = (FEA2LIST*) buffer;
  72.    }
  73.    addAllFrom(eaList);
  74. }
  75.  
  76.  
  77. ///////////////////////////////////////////////////////////////////////////////
  78. // Construct EAList from multi-valued EA
  79. //
  80. EAList::EAList(const IString& basename, const EA& ea) :
  81.                                    EASet(EALIST_DEFAULT_SIZE), mFEA2List(NULL) {
  82.  
  83.    USHORT type,
  84.           n      = ea.numValues(),     // this will throw an exception if not mv
  85.           digits = log10(n) + 1;
  86.    BYTE   flag   = ea.flag();
  87.    char   *p     = (char*) ea.value() + 2*sizeof(USHORT);   // skip header
  88.  
  89.    // extract type if single-typed   -------------------------------------------
  90.  
  91.    if (ea.type() == EAT_MVST) {
  92.       type = *(USHORT*) p;
  93.       p += sizeof(USHORT);
  94.       if (!EA::isLengthPreceded(type)) {
  95.          IString excText(IMessageText(ERR_INVALID_TYPE,MSG_FILE));
  96.          excText += " (" + EA::typeAsString(type) + ")";
  97.          IInvalidRequest exc(excText,0,IException::recoverable);
  98.          ITHROW(exc);
  99.       }
  100.    }
  101.  
  102.    // iterate through all entries   --------------------------------------------
  103.  
  104.    for (int i=1; i<=n; ++i) {
  105.       if (ea.type() == EAT_MVMT) {
  106.          type = *(USHORT*) p;
  107.          p += sizeof(USHORT);
  108.          if (!EA::isLengthPreceded(type)) {
  109.             IString excText(IMessageText(ERR_INVALID_TYPE,MSG_FILE));
  110.             excText += " (" + EA::typeAsString(type) + ")";
  111.             IInvalidRequest exc(excText,0,IException::recoverable);
  112.             ITHROW(exc);
  113.          }
  114.       }
  115.       USHORT length = *(USHORT*) p;
  116.       p += sizeof(USHORT);
  117.       IString name = basename + IString('.') + IString(i).rightJustify(digits,0);
  118.       add(EA(name,p,length,type,flag));
  119.       p += length;
  120.    }
  121. }
  122.  
  123.  
  124. ///////////////////////////////////////////////////////////////////////////////
  125. // Assignment
  126. //
  127. EAList& EAList::operator=(const EAList& eaList) {
  128.    if (&eaList == this)
  129.       return *this;
  130.  
  131.    if (mFEA2List)
  132.       delete mFEA2List;
  133.    if (eaList.mFEA2List) {
  134.       ULONG length = *(ULONG*) eaList.mFEA2List;
  135.       char *buffer = new char[length];
  136.       if (!buffer) {
  137.          IOutOfMemory exc(IMessageText(ERR_MEM_ALLOC_FAILED,MSG_FILE),0);
  138.          ITHROW(exc);
  139.       }
  140.       memcpy(buffer,(char*) eaList.mFEA2List,length);
  141.       mFEA2List = (FEA2LIST*) buffer;
  142.    }  else
  143.       mFEA2List = NULL;
  144.  
  145.    removeAll();
  146.    addAllFrom(eaList);
  147.    return *this;
  148. }
  149.  
  150.  
  151. ///////////////////////////////////////////////////////////////////////////////
  152. //  Read EAs from a given file. This function either reads all EAs of the
  153. //  file, or only the EAs given in the list.
  154. //
  155. EAList& EAList::read(PVOID fileRef,Boolean isPathName,Boolean onlyEAsFromList) {
  156.  
  157.    EAOP2 eaBuffer;
  158.    eaBuffer.oError = 0;
  159.  
  160.    if (onlyEAsFromList) {
  161.       if (!numberOfElements())                                 // nothing to do!
  162.          return *this;
  163.       eaBuffer.fpGEA2List = createGEA2LIST();
  164.       eaBuffer.fpFEA2List = createFEA2LISTBuffer(fileRef,isPathName);
  165.    } else {
  166.       DENA2 *eaEnumBuffer = queryDENA2(fileRef,isPathName);
  167.       if (!eaEnumBuffer) {
  168.          removeAll();
  169.          return *this;
  170.       }
  171.       eaBuffer.fpGEA2List = createGEA2LIST(eaEnumBuffer);
  172.       eaBuffer.fpFEA2List = createFEA2LISTBuffer(eaEnumBuffer);
  173.       delete eaEnumBuffer;
  174.    }
  175.  
  176.    APIRET rc;
  177.    if (isPathName)
  178.       rc = DosQueryPathInfo((PSZ)fileRef,FIL_QUERYEASFROMLIST,
  179.                                                        &eaBuffer,sizeof(EAOP2));
  180.    else
  181.       rc = DosQueryFileInfo(*(HFILE*)fileRef,FIL_QUERYEASFROMLIST,
  182.                                                        &eaBuffer,sizeof(EAOP2));
  183.    delete eaBuffer.fpGEA2List;
  184.    if (rc) {
  185.       IString api;
  186.       if (isPathName)
  187.          api = "DosQueryPathInfo";
  188.       else
  189.          api = "DosQueryFileInfo";
  190.       IException exc(ISystemErrorInfo(rc,api),rc,IException::recoverable);
  191.       ITHROW(exc);
  192.    }
  193.    if (!onlyEAsFromList)
  194.       removeAll();                         // this is save now
  195.    return convert();                       // converts FEA2LIST to EAList
  196. }
  197.  
  198.  
  199. ///////////////////////////////////////////////////////////////////////////////
  200. //  Write EAs to a given file.
  201. //
  202. EAList& EAList::write(PVOID fileRef,Boolean isPathName,Boolean useFEA2List) {
  203.  
  204.    if (!numberOfElements())        // nothing to do!
  205.       return *this;
  206.  
  207.    EAOP2 eaBuffer;
  208.    eaBuffer.oError     = 0;
  209.    eaBuffer.fpGEA2List = 0;
  210.  
  211.    if (useFEA2List)
  212.       eaBuffer.fpFEA2List = mFEA2List;
  213.    else
  214.       eaBuffer.fpFEA2List = createFEA2LIST();
  215.  
  216.    APIRET rc;
  217.    if (isPathName)
  218.       rc = DosSetPathInfo((PSZ)fileRef,FIL_QUERYEASIZE,&eaBuffer,sizeof(EAOP2),
  219.                                                                   DSPI_WRTTHRU);
  220.    else
  221.       rc = DosSetFileInfo(*(HFILE*)fileRef,FIL_QUERYEASIZE,
  222.                                                        &eaBuffer,sizeof(EAOP2));
  223.    if (rc) {
  224.       IString api;
  225.       if (isPathName)
  226.          api = "DosSetPathInfo";
  227.       else
  228.          api = "DosSetFileInfo";
  229.       IException exc(ISystemErrorInfo(rc,api),rc,IException::recoverable);
  230.       ITHROW(exc);
  231.    }
  232.    return *this;
  233. }
  234.  
  235.  
  236. ///////////////////////////////////////////////////////////////////////////////
  237. //  Remove EAs from a given file. This function either removes all EAs of the
  238. //  file, or only the EAs given in the list.
  239. //
  240. EAList& EAList::remove(PVOID fileRef,Boolean isPathName,Boolean onlyEAsFromList) {
  241.  
  242.    EAList removeList;
  243.  
  244.    if (onlyEAsFromList)
  245.       removeList = *this;
  246.    else
  247.       removeList.read(fileRef,isPathName,false);
  248.  
  249.    EAList::Cursor current(removeList);
  250.    forCursor(current)
  251.       removeList.elementAt(current).setValue("");
  252.  
  253.    removeList.write(fileRe